package com.laycoding.provider.handler;

import com.laycoding.common.entity.RpcMessage;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.concurrent.EventExecutorGroup;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

public class MyRegistryHandler extends ChannelInboundHandlerAdapter {


    private static ConcurrentHashMap<String,Object> registryMap =new ConcurrentHashMap<>();

    private static List<String> classList = new ArrayList<>();

    public MyRegistryHandler() {
        scanPackage("com.laycoding.provider.service");
    }

    private void registryService() {
        if(classList.size() == 0) {
            return;
        }
        for (String className: classList){
            try {
                Class<?> clazz = Class.forName(className);
                // 服务名称
                Class<?> anInterface = clazz.getInterfaces()[0];
                registryMap.put(anInterface.getName(), clazz.newInstance());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void scanPackage(String packageName) {
        ClassLoader classLoader = this.getClass().getClassLoader();
        URL url = classLoader.getResource(packageName.replaceAll("\\.", "/"));
        File dir = new File(url.getFile());
        File[] files = dir.listFiles();
        for (File file: files){
            if(file.isDirectory()){
                scanPackage(packageName + "." + file.getName());
            }else{
                // 拿出类名
                String className = packageName + "." + file.getName().replace(".class", "").trim();
                classList.add(className);
            }
        }
        registryService();
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

        RpcMessage rpcMessage =(RpcMessage) msg;

        String className = rpcMessage.getClassName();
        Object res =new Object();
        if (registryMap.containsKey(className)){
            Object clazz = registryMap.get(className);
            Method method = clazz.getClass().getMethod(rpcMessage.getMethodName(), rpcMessage.getParams());
            res = method.invoke(clazz, rpcMessage.getValues());
        }
        System.out.println(res.toString());
        ctx.channel().writeAndFlush(res);
        ctx.close();
    }
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }
}
